const axios = require('axios');
const crypto = require('crypto');
const config = require('../../config/config');
const { setupLogger } = require('../../utils/logger');

class BinanceService {
  constructor() {
    this.logger = setupLogger();
    this.baseUrl = config.dataSources.binance.baseUrl;
    this.apiKey = config.dataSources.binance.apiKey;
    this.apiSecret = config.dataSources.binance.apiSecret;
  }

  async fetchData() {
    try {
      this.logger.info('开始获取Binance数据...');
      
      const data = [];
      
      // 获取24小时价格变化统计
      const priceStats = await this.get24hrTicker();
      data.push(...priceStats);
      
      // 获取交易对信息
      const exchangeInfo = await this.getExchangeInfo();
      data.push(...exchangeInfo);
      
      // 获取最新价格
      const latestPrices = await this.getLatestPrices();
      data.push(...latestPrices);
      
      // 获取订单簿深度（热门交易对）
      const orderBookData = await this.getOrderBookDepth(['BTCUSDT', 'ETHUSDT', 'BNBUSDT']);
      data.push(...orderBookData);
      
      this.logger.info(`Binance数据获取完成，共获取 ${data.length} 条数据`);
      return data;
    } catch (error) {
      this.logger.error('Binance数据获取失败:', error);
      return [];
    }
  }

  async get24hrTicker() {
    try {
      const response = await axios.get(`${this.baseUrl}/ticker/24hr`);
      
      return response.data
        .filter(ticker => parseFloat(ticker.volume) > 1000) // 过滤低交易量
        .slice(0, 100) // 限制数量
        .map(ticker => ({
          source: 'binance',
          type: '24hr_ticker',
          symbol: ticker.symbol,
          price: parseFloat(ticker.lastPrice),
          priceChange: parseFloat(ticker.priceChange),
          priceChangePercent: parseFloat(ticker.priceChangePercent),
          volume: parseFloat(ticker.volume),
          quoteVolume: parseFloat(ticker.quoteVolume),
          openPrice: parseFloat(ticker.openPrice),
          highPrice: parseFloat(ticker.highPrice),
          lowPrice: parseFloat(ticker.lowPrice),
          count: parseInt(ticker.count),
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error('获取24小时价格统计失败:', error);
      return [];
    }
  }

  async getExchangeInfo() {
    try {
      const response = await axios.get(`${this.baseUrl}/exchangeInfo`);
      
      return response.data.symbols
        .filter(symbol => symbol.status === 'TRADING')
        .slice(0, 50) // 限制数量
        .map(symbol => ({
          source: 'binance',
          type: 'exchange_info',
          symbol: symbol.symbol,
          baseAsset: symbol.baseAsset,
          quoteAsset: symbol.quoteAsset,
          status: symbol.status,
          permissions: symbol.permissions,
          filters: symbol.filters,
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error('获取交易对信息失败:', error);
      return [];
    }
  }

  async getLatestPrices() {
    try {
      const response = await axios.get(`${this.baseUrl}/ticker/price`);
      
      return response.data
        .slice(0, 100) // 限制数量
        .map(price => ({
          source: 'binance',
          type: 'latest_price',
          symbol: price.symbol,
          price: parseFloat(price.price),
          timestamp: new Date().toISOString()
        }));
    } catch (error) {
      this.logger.error('获取最新价格失败:', error);
      return [];
    }
  }

  async getOrderBookDepth(symbols) {
    const data = [];
    
    for (const symbol of symbols) {
      try {
        const response = await axios.get(`${this.baseUrl}/depth`, {
          params: {
            symbol: symbol,
            limit: 20
          }
        });
        
        data.push({
          source: 'binance',
          type: 'order_book',
          symbol: symbol,
          bids: response.data.bids.map(bid => ({
            price: parseFloat(bid[0]),
            quantity: parseFloat(bid[1])
          })),
          asks: response.data.asks.map(ask => ({
            price: parseFloat(ask[0]),
            quantity: parseFloat(ask[1])
          })),
          lastUpdateId: response.data.lastUpdateId,
          timestamp: new Date().toISOString()
        });
        
        // 避免过快请求
        await this.delay(100);
      } catch (error) {
        this.logger.error(`获取 ${symbol} 订单簿失败:`, error.message);
        continue;
      }
    }
    
    return data;
  }

  async getKlines(symbol, interval = '1h', limit = 100) {
    try {
      const response = await axios.get(`${this.baseUrl}/klines`, {
        params: {
          symbol: symbol,
          interval: interval,
          limit: limit
        }
      });
      
      return response.data.map(kline => ({
        source: 'binance',
        type: 'kline',
        symbol: symbol,
        interval: interval,
        openTime: parseInt(kline[0]),
        open: parseFloat(kline[1]),
        high: parseFloat(kline[2]),
        low: parseFloat(kline[3]),
        close: parseFloat(kline[4]),
        volume: parseFloat(kline[5]),
        closeTime: parseInt(kline[6]),
        quoteAssetVolume: parseFloat(kline[7]),
        numberOfTrades: parseInt(kline[8]),
        takerBuyBaseAssetVolume: parseFloat(kline[9]),
        takerBuyQuoteAssetVolume: parseFloat(kline[10]),
        timestamp: new Date().toISOString()
      }));
    } catch (error) {
      this.logger.error(`获取 ${symbol} K线数据失败:`, error);
      return [];
    }
  }

  // 私有API方法（需要API密钥）
  async getAccountInfo() {
    if (!this.apiKey || !this.apiSecret) {
      this.logger.warn('Binance API密钥未配置，跳过账户信息获取');
      return null;
    }

    try {
      const timestamp = Date.now();
      const queryString = `timestamp=${timestamp}`;
      const signature = crypto
        .createHmac('sha256', this.apiSecret)
        .update(queryString)
        .digest('hex');

      const response = await axios.get(`${this.baseUrl}/account`, {
        headers: {
          'X-MBX-APIKEY': this.apiKey
        },
        params: {
          timestamp: timestamp,
          signature: signature
        }
      });

      return {
        source: 'binance',
        type: 'account_info',
        balances: response.data.balances
          .filter(balance => parseFloat(balance.free) > 0 || parseFloat(balance.locked) > 0)
          .map(balance => ({
            asset: balance.asset,
            free: parseFloat(balance.free),
            locked: parseFloat(balance.locked)
          })),
        canTrade: response.data.canTrade,
        canWithdraw: response.data.canWithdraw,
        canDeposit: response.data.canDeposit,
        timestamp: new Date().toISOString()
      };
    } catch (error) {
      this.logger.error('获取账户信息失败:', error);
      return null;
    }
  }

  delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

module.exports = new BinanceService();

